home *** CD-ROM | disk | FTP | other *** search
/ GIFs Galore 1993 September / Walnut Creek GIFs Galore CDROM WIN-MAC (Walnut Creek CDROM)(September 1993).iso / pc / viewers / msdos / gifdoc.arc / DEGIF.DOC next >
Text File  |  1988-03-21  |  17KB  |  505 lines

  1.  
  2.  
  3.  
  4.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  5.  
  6.  
  7.  
  8. 1.0 INTRODUCTION
  9.  
  10.      DEGIF is a Turbo Pascal Unit to decode graphic images stored in 
  11. CompuServe's Graphic Interchange Format (GIF).  With this unit you can write 
  12. your own GIF decoder or add GIF to any application.  "GIF" and "Graphic 
  13. Interchange Format" are trademarks of H & R Block, Inc.  The GIF standard 
  14. itself is in the public domain.
  15.  
  16.      This unit is fully documented but we will not release the source code 
  17. at this time.  This is a shareware product with a registration fee of $25 
  18. payable to Cyborg Software Systems, Inc.  3119 Cossell Drive, Indianapolis, 
  19. IN 46224.  This unit, the documentation and the source and executable code 
  20. for DEGIFER are all Copyright 1988 by Cyborg Software Systems, Inc.
  21.  
  22.      You may use this material for personal non-commercial use.  If you like 
  23. it we ask you to register it.  If you distribute it for free you must 
  24. distribute it in its original ARC form with all files intact.  If you 
  25. distribute it for a fee or if you wish to use DEGIF in any commercial 
  26. application or custom programming written for fee or under contract, you 
  27. must register it.  Violation of the above terms infringes our copyright.  
  28. Registered users will receive the next update free of charge.  Further 
  29. updates will cost registered users $5.
  30.  
  31.      Parts of this code are very loosely based on EXPANDER.INC by Bob Berry 
  32. which was a Turbo Pascal 3.0 translation of EXPANDER.C written in C by Steve 
  33. Wilhite.  Sincere thanks and credit to them.
  34.  
  35. 2.0  GIF DECODING
  36.  
  37.      The best way we know to document the DEGIF unit is to give an example 
  38. program called DEGIFER.  DEGIFER is a very, very primitive GIF display 
  39. program for CGA graphics.  It makes no attempts to match colors.  It just 
  40. plots points in (COLOR mod 4).  On 2 color images its great.  Most 16 color 
  41. images are viewible.  Beyond that you're on your own.
  42.  
  43.      You should print out a copy of DEGIFER.PAS and follow it along its main 
  44. routine as we go.
  45.  
  46. 2.1 Initialization
  47.  
  48.      The first thing you must do is pass a procedure pointer to your 
  49. routines called GetByte and PutByte.  GetByte must be a far-call function to 
  50. retrieve one byte from the GIF file.  PutByte must be a far-call procedure 
  51. to put one pixel on the screen.  We will discuss these routines in section 
  52. 3.0 below.  AddrGetByte and AddrPutByte are a global pointers declared in 
  53. the DEGIF unit but you must initialize them.
  54.  
  55.      The next few lines of DEGIFER's main routine engage the CRT unit and 
  56. prints the copyright notice.  A file name is retrieved from the command line 
  57. or the user is prompted for one.  The file is opened.  This is the file that 
  58. GetByte gets its bytes from.
  59.  
  60.      The variables SkipIt, EOFin, Done, BufIndx and Count are initialized.  
  61.  
  62.  
  63. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 1.
  64.  
  65.  
  66.  
  67.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  68.  
  69.  
  70. They are specific to this demo and your application may not need them.
  71.  
  72.      The DEGIF unit defines the following....
  73.  
  74.           Type MapType=(Global,Local);
  75.  
  76.      GIF files may or may not have a global color map and or a local color 
  77. map for multiple image files.  DEGIF needs its variable CurMap:MapType to be 
  78. initialized before you begin.
  79.  
  80.  
  81. 2.2 Procedure GetGIFSig
  82.  
  83.      All valid GIF files begin with a 6 byte signature.  The DEGIF unit 
  84. provides a procedure GetGIFSig to retrieve it.  After calling GetGIFSig the 
  85. global string GIFSig should contain the string.  As of this writing (March 
  86. 1988) the only valid string is 'GIF87a'.
  87.  
  88. 2.3 Procedure GetScrDes
  89.  
  90.      Following the GIF signature in a GIF file is the screen description.  
  91. The DEGIF unit provides a procedure GetScrDes to retrieve it and initialize 
  92. several global variables.
  93.  
  94.      ScreenWidth and ScreenHeight are type Word and contain the screen width 
  95. and height in pixels.  All images in this file will fit in this virtual 
  96. screen space.  Its up to you to scale, clip or scroll the image if it 
  97. doesn't fit your physical screen.  There is no information anywhere in 
  98. current GIF files to help determine the proper aspect ratio.  You have to 
  99. just guess that in all likelihood screens of 320 x 200, 640 x 200, 320 x 400 
  100. or 640 x 400 are really all supposed to be of the same aspect ratio.  What 
  101. you do with stuff like 640 x 350 or 640 x 480 on a screen that won't hold it 
  102. is up to you.
  103.  
  104.      MapExists[Global] is a boolean that tells you if there is a global 
  105. color map for this file.
  106.  
  107.      BitsOfColorPerPrimary is a Word but the only valid values are [1..8].  
  108. I was just too lazy to declare it as a byte or sub-range type <heheh>.  It 
  109. is the topic of much debate among GIF developers as to how useful it is.  It 
  110. isn't necessary and my experience is it is unreliable.  For EGA created 
  111. images its value should be 2 because each primary color (red, green and 
  112. blue) is designated by 2 bits.  EGA's can therefore have 2^(2+2+2)=64 
  113. possible colors.  The GIF file might contain only 16 so 
  114. BitsOfColorPerPrimary doesn't tell you how many you can display at once or 
  115. how many colors are in this image.
  116.  
  117.      BitsPerPixel[Global] is a word that does tell you.  You really don't 
  118. need this value but we give it to you anyway.  We provide also provide 
  119. NumberOfColors[Global] which again is a word but it is in the range 
  120. [1..256].  It is computed by...
  121.  
  122.      NumberOfColors[Global]:= (1 shl BitsPerPixel[Global]);
  123.  
  124.  
  125.  
  126. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 2.
  127.  
  128.  
  129.  
  130.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  131.  
  132.  
  133.      This means GIF color maps always contain 2, 4, 8, 16, 32, 64, 128 or 
  134. 256 entries.  The image may not actually contain that many colors.  It may 
  135. use fewer.  I have no problem with 16 color images that contain only 10 or 
  136. 12 colors.  It really raises my dandruff when I download 256 color images 
  137. with 31 colors!!!  Editorial over.
  138.  
  139.      Some GIF files are composed of multiple small images that may overlap 
  140. or may not fill the screen.  The standard says you should first fill in a 
  141. background before plotting the images.  Some decoders don't bother.  They 
  142. leave the background black.  DEGIF gives you BackgrColorIndex which tells 
  143. you what color to paint the background.
  144.  
  145.      Next DEGIFER calls DisplayScrDes.  This is its own routine which not 
  146. only tells the user the information from the screen descriptor, it also 
  147. attempts to correct aspect ratio by squeezing the image horizontally, 
  148. smashing it vertically or clipping it if that doesn't work.  You are 
  149. responsible for coming up with such topological gymnastics and should feel 
  150. free to do it however you want.
  151.  
  152. 2.4 Procedure GetColorMap
  153.  
  154.      The GIF standard provides for an optional global color map.  Most GIF 
  155. files contain one.  GetScrDes sets the boolean MapExists[Global] to true if 
  156. there is a global map.  The map is put in the following arrays....
  157.  
  158.      RedValue,GreenValue,BlueValue: array [0..255] of byte;
  159.  
  160.      Only values in the range [0..NumberOfColors[Global]-1] are defined.  
  161. They are intensity values from [0..255] for the red, blue and green 
  162. components of the color.
  163.  
  164.      After calling GetColorMap you must decide on a mapping method.  This is 
  165. the proverbial thing that "separates the men from the boys" when it comes to 
  166. implementing GIF.  DEGIFER does a total cop-out and ignores the map 
  167. completely.  It has the following statements...
  168.  
  169.      if MapExists[Global] then GetColorMap; 
  170.      DoMapping;
  171.  
  172.      ...but you'll probably want to implement it as...
  173.  
  174.      if MapExists[Global] 
  175.       then begin GetColorMap; DoMapping end
  176.       else UseDefaultMap;
  177.  
  178.      The job of your DoMapping is to fill the array Color which is defined 
  179. by the DEGIF unit as...
  180.  
  181.           Color: array [Global..Local,0..255] of byte;
  182.  
  183.      DoMapping should look like this...
  184.  
  185.  
  186. procedure DoMapping;
  187.  
  188.  
  189. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 3.
  190.  
  191.  
  192.  
  193.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  194.  
  195.  
  196.  var I:integer;
  197.  begin
  198.   for I:=0 to NumberOfColors[CurMap]-1 do 
  199.      Color[CurMap,I]:= { Some function of }
  200.                        {  RedValue[I],    }
  201.                        {  BlueValue[I] &  }
  202.                        {  GreenValue[I]   }
  203.   end;
  204.  
  205.      Here is a sample DoMapping that computes a least squares mapping for a 
  206. 16 color mode on a PCjr or Tandy 1000...
  207.  
  208. procedure DoMapping;
  209. const
  210.  MyRed:array [0..15] of byte=
  211. (000,000,000,000, 170,170,170,170, 085,085,085,085, 255,255,255,255);
  212.  MyGreen:array [0..15] of byte=
  213. (000,000,170,170, 000,000,170,170, 085,085,255,255, 085,085,255,255);
  214.  MyBlue:array [0..15] of byte=
  215. (000,170,000,170, 000,170,000,170, 085,255,085,255, 085,255,085,255);
  216. var I,J,K:byte; D1,D2:real;
  217.  begin
  218.   for I:=0 to NumberOfColors[CurMap]-1 do
  219.    begin
  220.     D1:=9999.99;  K:=0;
  221.     for J:=0 to 15 do
  222.      begin
  223.       D2:= SQRT( (RedValue[I]-MyRed[J])     * (RedValue[I]-MyRed[J])+
  224.                (GreenValue[I]-MyGreen[J]) * (GreenValue[I]-MyGreen[J])+
  225.                (BlueValue[I]-MyBlue[J])   * (BlueValue[I]-MyBlue[J]) );
  226.       if D2 < D1 then begin K:=J; D1:=D2 end
  227.      end;
  228.     Color[CurMap,I]:=K
  229.    end
  230.  end;
  231.  
  232. 2.5 Reading blocks
  233.  
  234.      Its time now to get down to actual plotting!  DEGIFER uses the GRAPH3 
  235. procedure GraphColorMode to get into CGA's 320 x 200 x 4 color mode.
  236.  
  237.      The next thing to appear in a GIF file is a block.  There are currently 
  238. only two types.  Image blocks are preceded by a comma.  Extension blocks are 
  239. preceded by an exclamation point.  Any characters other than a ',' or '!' 
  240. may be ignored.  Keep reading until there is nothing left to read.  
  241. Currently no extension blocks are defined.  The DEGIF unit has a procedure 
  242. that lets you skip extension blocks.  It is cleverly called SkipExtendBlock.
  243.  
  244. 2.6 Procedure GetImageDescription
  245.  
  246.      After finding an image block which begins with a comma you should call 
  247. DEGIF's GetImageDescription procedure.  It sets up the following global 
  248. variables declared in DEGIF.  Unless noted, all are type word.
  249.  
  250.  
  251.  
  252. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 4.
  253.  
  254.  
  255.  
  256.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  257.  
  258.  
  259.      ImageLeft and ImageTop define the coordinates of this image relative to 
  260. the screen description.  A value of 0,0 is the upper left corner of the 
  261. screen.
  262.  
  263.      ImageWidth and ImageHeight give the dimensions of this image.  The 
  264. image may overlap previous images.  It may or may not fill the screen.  It 
  265. should never exceed the screen description.
  266.  
  267.      MapExists[Local] is a boolean that tells you if a local color map 
  268. exists for this image.  If no local map exists then you should use the 
  269. global map.  Subsequent images never use old local maps.  They always use 
  270. their own local maps or they revert to the global map.  The following code 
  271. implements this properly.
  272.  
  273.           if MapExists[Local]
  274.            then begin CurMap:=Local; GetColorMap; DoMapping end
  275.            else CurMap:=Global;
  276.      
  277.      Note that GetColorMap and DoMapping depend on CurMap.
  278.  
  279.      The boolean variable Interlaced tells you how to plot the scan lines.  
  280. See section 3.2 for a discussion of interlaced images.
  281.  
  282.      BitsPerPixel[Local] and NumberOfColors[Local] tell you the same things 
  283. about the local map that their global brothers tell you about the global 
  284. map.
  285.  
  286.      The AdjustImage routine is specific to DEGIFER and you may or may not 
  287. need it.
  288.  
  289. 2.7 Function ExpandGIF
  290.  
  291.      The data blocks which follow are the image data index values compressed 
  292. in a variable length 12 bit-maximum modified LZW compression scheme.
  293.  
  294.      HUH?
  295.  
  296.      That's what I said when I first became a GIF developer.  They just 
  297. handed me a bunch of code written in "C" by Steve Wilhite.  They said just 
  298. use this code and everything will be ok.  There was one problem.  I don't 
  299. know "C"!  Enter Bob Berry who sees C and Pascal.  My first GIF decoder used 
  300. his Turbo Pascal 3.0 translation from Wilhite's "C".  I plugged.  It 
  301. chugged.  Out came GIF!  Presto!  
  302.  
  303.      Since then I've rewritten ExpandGIF several times on my own and I 
  304. understand "image data index values compressed in a variable length 12 bit 
  305. maximum modified LZW compression scheme."
  306.  
  307.      But you don't need to.
  308.  
  309.      ExpandGIF calls your GetByte routine to get compressed data one byte at 
  310. a time.  It does all the magic by calling your PutByte routine to put the 
  311. dots on the screen.
  312.  
  313.  
  314.  
  315. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 5.
  316.  
  317.  
  318.  
  319.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  320.  
  321.  
  322.      When the entire image is done ExpandGIF returns an integer.  Anything 
  323. other than a 0 is an error.
  324.  
  325. 3.0 ROUTINES YOU PROVIDE
  326.  
  327.      Routines like DoMapping and DisplayScreenDescription and AdjustImage 
  328. are so totally your responsibility that we really can't say much more about 
  329. them because you may want to do them differently.  The GetByte and PutByte 
  330. need more explanation.
  331.  
  332.      DO NOT FORGET TO INCLUDE THESE TWO LINES!
  333.  
  334.            AddrGetByte:=@GetByte;
  335.            AddrPutByte:=@PutByte;
  336.  
  337. 3.1 Function GetByte
  338.  
  339.      You must provide a function GetByte:Byte which returns sequential bytes 
  340. from somewhere.  It will most likely be a file but DEGIF could get its 
  341. information from a modem to view GIF on-line.  You'd need more information 
  342. to do this than is provided here.  (When I figure it out myself I'll have a 
  343. new DEGIF uploaded.)
  344.  
  345.      This function must be a far function and is compiled with the {$F+} 
  346. directive.  The simplest GetByte is..
  347.  
  348. {$F+}
  349. function GetByte:byte;
  350.  var b:byte;
  351.  begin
  352.   Read(InFile,b);
  353.   GetByte:=b
  354.  end;
  355. {$F-}
  356.  
  357. 3.2 Procedure PutByte(Pix:integer)
  358.  
  359.      PutByte isn't that simple.  It passes you an integer in the range 
  360. [0..255] that is the index to the Color array.  PutByte should plot the 
  361. color given by Color[CurMap,Pix] at location x,y.  The catch is what are x 
  362. and y?
  363.  
  364.      On non-interlaced images you just start at X:=ImageLeft and 
  365. Y:=ImageTop.  You plot points along Y and increment X until you've plotted 
  366. ImageWidth of them.  That is until X=ImageLeft+ImageWidth.  Then you reset X 
  367. to ImageLeft, increment Y and plot the next line.
  368.  
  369.      Interlaced images start with Y=ImageTop but they make 4 interlaced 
  370. passes.  Pass 1 begins at ImageTop+0 and plots every 8th line.  Pass 2 
  371. starts at ImageTop+4 and also plots every 8th line.  Pass 3 starts at 
  372. ImageTop+2 and plots every 4th line.  Pass 4 starts at ImageTop+1 and plots 
  373. every other line.  These 4 passes fill the screen.
  374.  
  375.      In DEGIFER's PutByte routine I invented a Pass 5 which starts at 
  376.  
  377.  
  378. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 6.
  379.  
  380.  
  381.  
  382.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  383.  
  384.  
  385. ImageTop+0 and plots every line.  My procedure AdjustImage contains...
  386.  
  387.      if Interlaced then Pass:=1 else Pass:=5;
  388.  
  389.      This fully implements interlaced images.
  390.  
  391.      The PutByte routine must be compiled with the {$F+} far directive on.
  392.  
  393. 4.0 INTERFACE
  394.  
  395.      Here is the interface section of the DEGIF unit.
  396.  
  397.  
  398. unit degif;
  399. interface
  400.  
  401. type MapType=(Global,Local);
  402.  
  403. var  GIFSig:String[6];        {GIF ID string usually = 'GIF87a'}
  404.      CurMap:MapType;          {Current Map in use}
  405.      BitsPerPixel,            {in this image}
  406.      NumberOfColors           {in this image}
  407.        :array [Global..Local] of word;
  408.      BackgrColorIndex,        {Background Color index}
  409.      BitsOfColorPerPrimary,   {For example on EGA=2}
  410.      ImageLeft,             {Left edge of image relative to virtual screen}
  411.      ImageTop,              {Top edge of image relative to virtual screen}
  412.      ImageWidth,              {in pixels}
  413.      ImageHeight,             {in pixels}
  414.      ScreenHeight,            {in pixels}
  415.      ScreenWidth:word;        {in pixels}
  416.      MapExists:array [Global..Local] of boolean;
  417.      Interlaced:boolean;
  418.      AddrGetByte,             {Pointer to user supplied GetByte}
  419.      AddrPutByte:pointer;     {Pointer to user supplied PutByte}
  420.      RedValue,GreenValue,BlueValue: array [0..255] of byte;
  421.      Color:    array [Global..Local,0..255] of byte;
  422.  
  423. function ExpandGif: integer;
  424.  
  425. procedure GetColorMap;
  426.  
  427. procedure GetGIFSig;
  428.  
  429. procedure GetImageDescription;
  430.  
  431. procedure GetScrDes;
  432.  
  433. procedure SkipExtendBlock;
  434.  
  435. 5.0 FINAL WORDS
  436.  
  437.      This unit is written entirely in Turbo Pascal 4.0 and contains no 
  438. assembler or Inline code.  My #1 goal was to get this available as soon as 
  439.  
  440.  
  441. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 7.
  442.  
  443.  
  444.  
  445.                   DEGIF TURBO PASCAL UNIT DOCUMENTATION
  446.  
  447.  
  448. possible.  My #2 goal will be to make it fast.  After that I'll add on-line 
  449. viewing support and any new extensions to the GIF87a standard.
  450.  
  451.      To make it worth my trouble I need your support.  Please show your 
  452. appreciation and register this product.
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504. Copyright (c) 1988 Cyborg Software Systems, Inc.             page 8.
  505.